package com.rybbaby.tss.tasks.core.web.service;

import com.rybbaby.tss.tasks.core.bean.PageBean;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.jdbc.core.SqlParameter;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @description 基础Service接口
 *
 * @author 谢进伟
 *
 * @createDate 2016年2月3日 下午9:14:33
 */
public interface IBaseService<T> {
	
	/**
	 * 根据传入的实体持久化对象
	 * 
	 * @param entity
	 *            需要持久化的对象
	 */
	
	public abstract Serializable save(T entity);
	
	/**
	 * 批量保存实体
	 * 
	 * @param entitys
	 *            需要保存的实体集合
	 */
	
	public abstract boolean jdbcBatchSave(List<T> entitys) throws Exception;
	
	/**
	 * 批量修改实体
	 * 
	 * @param entitys
	 *            需要修改的实体集合
	 */
	
	public abstract boolean batchUpdate(List<T> entitys) throws Exception;
	
	/**
	 * 批量修改实体
	 *
	 * @param entitys
	 *            需要修改的实体集合
	 * @param isUpdateNullField
	 *            是否更新空值属性
	 */
	public boolean batchUpdate(List<T> entitys, boolean isUpdateNullField) throws Exception;
	
	/**
	 * 批量执行sql
	 *
	 * @param sqls
	 *            需要执行的sql
	 * @return
	 */
	boolean batchUpdate(String... sqls);
	
	/**
	 * 批量删除记录
	 * 
	 * @param ids
	 *            需要删除的记录主键集合
	 */
	
	public abstract boolean batchDelete(Integer ids[]) throws Exception;
	
	/**
	 * 批量删除记录
	 * 
	 * @param ids
	 *            需要删除的记录主键集合
	 */
	
	public abstract boolean batchDelete(String ids[]) throws Exception;
	
	/**
	 * 批量删除对象
	 * 
	 * @param entitys
	 *            需要删除的对象集合
	 */
	
	public abstract void batchDelete(Collection<T> entitys);
	
	/**
	 * 持久化一个对象
	 * 
	 * @param entity
	 *            需要持久化的对象
	 */
	
	public abstract void saveOrUpdate(T entity);
	
	/**
	 * 删除一个对象
	 * 
	 * @param entity
	 *            需要删除的对象
	 */
	public abstract void delete(T entity);
	
	/**
	 * 根据Id获取一个实体对象
	 * 
	 * @param id
	 *            主键id
	 */
	public abstract T get(Serializable id);
	
	/**
	 * 根据属性值该实体的唯一记录，如果有多条记录，将返回第一条记录
	 * 
	 * @param propertyName
	 *            属性名
	 * @param value
	 *            属性值
	 * @return
	 */
	public abstract T findUniqueByProperty(String propertyName, Object value);
	
	/**
	 * 根据属性值该实体类的记录
	 * 
	 * @param propertyName
	 *            属性名
	 * @param value
	 *            属性值
	 * @return
	 */
	
	public abstract List<T> findByProperty(String propertyName, Object value);
	
	/**
	 * 加载某一个实体的所有数据
	 */
	
	public abstract List<T> loadAll();
	
	/**
	 * 删除一个实体类指定Id的对象
	 * 
	 * @param id
	 *            主键Id
	 */
	
	public abstract void deleteEntityById(Serializable id);
	
	/**
	 * 通过hql 查询语句查找对象，并以实体类型集合返回
	 * 
	 * @param hql
	 *            hql语句
	 * @return
	 */
	
	public abstract List<T> findByHql(String hql);
	
	/**
	 * 通过sql语句更新数据
	 * 
	 * @param sql
	 *            更新类型sql语句
	 *            （新增、删除、删除）
	 */
	public abstract int updateBySql(String sql);
	
	/**
	 * 通过sql查询语句查找对象
	 * 
	 * @param sql
	 *            查询类型sql语句，sql语句中的查询库字段别名，必须是cls参数中存在的属性名
	 * @param params
	 *            SQL语句中的参数，请注意参数与sql语句中参数暂未符?的对应关系
	 * @return
	 * @throws Exception
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public abstract List<T> findListBySql(String sql, Object... params) throws Exception;
	
	/**
	 * 将原生sql返回的结果集注入到指定的可不受Hibernate管制实体bean中（待测试）
	 * 
	 * @param sql
	 *            查询语句
	 * @param columnAliases
	 *            手动指定需要返回的数据库字段别名，别名必须是cls参数中存在的属性名
	 * @param params
	 *            SQL语句中的参数，请注意参数与sql语句中参数暂未符?的对应关系
	 * @return
	 */
	
	public abstract List<T> findListBySql(String sql, String[] columnAliases, Object... params);
	
	/**
	 * 根据属性值该实体类的记录
	 * 
	 * @param propertyName
	 *            属性名
	 * @param value
	 *            属性值
	 * @param isAsc
	 *            是否升序排列
	 * */
	
	public abstract List<T> findByPropertyisOrder(String propertyName, Object value, boolean isAsc);
	
	/**
	 * 执行hql语句查询查找对象
	 * 
	 * @param hql
	 *            hql语句
	 * 
	 * @param params
	 *            参数
	 */
	
	public abstract List<T> findByHql(String hql, Object[] params);
	
	/**
	 * 通过DetachedCriteria查询指定下标开始查询指定数据量的的数据集
	 * 
	 * @param dc
	 *            查询条件对象
	 * @param pageNo
	 *            当前页
	 * @param pageSize
	 *            每一页显示的记录数
	 */
	
	public abstract PageBean pageList(DetachedCriteria dc, int pageNo, int pageSize);
	
	/**
	 * 使用指定的检索标准检索数据并分页返回数据
	 * 
	 * @param sql
	 *            要执行查询的sql，此sql只需要专注查询，不需要写分页相关的代码
	 * @param pageNo
	 *            当前页
	 * @param pageSize
	 *            每一页显示的记录数
	 * @return
	 */
	public PageBean pageList(String sql, int pageNo, int pageSize);
	
	/**
	 * @return 获取Hibernate 当前，事务必须是开启的(Required)，否则获取不到
	 */
	public abstract Session getSession();
	
	/**
	 * 通过hql 查询语句查找对象,并以键值对返回
	 * 
	 * @param hql
	 *            hql语句
	 * @return
	 */
	public abstract Map<Object , Object> getHashMapbyHql(String hql);
	
	/**
	 * 执行更新操作，并返回受影响行数
	 * 
	 * @param sql
	 *            sql语句
	 * 
	 * @param params
	 *            参数
	 */
	public abstract Integer executeSql(String sql, List<Object> params);
	
	/**
	 * 执行更新操作，并返回受影响行数
	 * 
	 * @param sql
	 *            sql语句
	 * 
	 * @param params
	 *            参数
	 */
	public abstract Integer executeSql(String sql, Object[] params);
	
	/**
	 * 执行更新操作，并返回受影响行数
	 * 
	 * @param sql
	 *            sql语句
	 * 
	 * @param params
	 *            参数
	 */
	public abstract Integer executeSql(String sql, Map<String, Object> params);
	
	/**
	 * 执行更新操作，并返回受影响的行数
	 * 
	 * @param sql
	 *            sql语句
	 * 
	 * @param params
	 *            参数
	 */
	public abstract Object executeSqlReturnKey(String sql, Map<String, Object> params);
	
	/**
	 * 执行sql查询，并返回结果集
	 * 
	 * @param sql
	 *            sql语句
	 * @param params
	 *            参数
	 */
	public abstract List<Map<String , Object>> findForJdbc(String sql, Object[] params);
	
	/**
	 * 执行查询操作，并将结果集映射到map中<br>
	 * <span style="color:red;">返回的结果集大小必须是1</span>
	 * 
	 * @param sql
	 *            sql语句
	 * 
	 * @param params
	 *            参数
	 */
	public abstract Map<String , Object> findOneForJdbc(String sql, Object[] params);
	
	/**
	 * 执行hql更新数据，并返回受影响行数
	 * 
	 * @param hql
	 *            hql语句
	 */
	public abstract Integer executeHql(String hql);
	
	/**
	 * 执行存储过程(有结果集)
	 * 
	 * @param proc
	 *            存储过程名称
	 * @param params
	 *            存储过程参数,如：<br>
	 *            new SqlInOutParameter("inOutName" , Types.VARCHAR)
	 *            表示参数“inOutName”为输入输出参数<br>
	 *            new SqlOutParameter("outId" , Types.INTEGER)
	 *            表示参数“outId”为输出参数<br>
	 * @param outParam
	 *            除结果集外的输出参数容器，如果输出参数不需要接收可传入null
	 * @return
	 */
	public abstract List<Map<String , Object>> callableStatementByName(String proc, List<SqlParameter> params, Map<String, Object> outParam);
	
	/**
	 * 修改一个实体类
	 * 
	 * @param entity
	 *            需要修改的实体类对象
	 */
	
	public abstract void updateEntitiy(T entity);
	
	/**
	 * 使用占位符的方式填充值 请注意：like对应的值格式："%"+username+"%" Hibernate Query
	 * 
	 * @param hql
	 *            hql语句
	 * @param values
	 *            占位符号?对应的值，顺序必须一一对应 可以为空对象数组，但是不能为null
	 */
	
	public abstract List<T> executeQuery(String hql, Object[] values);
	
	/**
	 * 执行存储过程(无结集)
	 * 
	 * @param proc
	 *            存储过程名称
	 * @param params
	 *            存储过程参数,如：<br>
	 *            new SqlInOutParameter("inOutName" , Types.VARCHAR)
	 *            表示参数“inOutName”为输入输出参数<br>
	 *            new SqlOutParameter("outId" , Types.INTEGER)
	 *            表示参数“outId”为输出参数<br>
	 * @return
	 */
	public abstract Map<String , Object> callableStatementByName(String proc, List<SqlParameter> params);
	
	/**
	 * 获取实体对应表或试图中的记录总数
	 * 
	 * @return
	 */
	
	public abstract int getTableDataCount();
	
	/**
	 * 通过DetachedCriteria查询数据集
	 * 
	 * @param dc
	 *            查询条件对象
	 */
	
	public abstract List<T> findByDetached(DetachedCriteria dc);
	
	/**
	 * 批量保存实体
	 * 
	 * @param entitys
	 *            需要保存的实体集合
	 */
	
	public List<Serializable> hibernateBatchSave(List<T> entitys) throws Exception;
	
	/**
	 * 根据多个Id查询对象
	 * 
	 * @param cls
	 *            类型
	 * @param Ids
	 *            主键数组
	 * @return
	 */
	public List<T> loadByMultipleId(Class<T> cls, Object[] Ids);
	
	/**
	 * 根据多个Id查询对象
	 * 
	 * @param cls
	 *            类型
	 * @param ids
	 *            主键集合
	 * @return
	 */
	public List<T> loadByMultipleId(Class<T> cls, List<String> ids);
	
	/**
	 * 根据Sql查询
	 * 
	 * @param sql
	 *            sql预警
	 * @param params
	 *            参数
	 * @return
	 */
	public List<Map<String , Object>> findList(String sql, Object[] params);
}
